#include "event/loop.hpp"
#include "network/sockaddr.hpp"
#include "network/socket_fd.hpp"

#include <memory>

namespace ibox::network {
using namespace ibox;
class TcpConnection;

class TcpAcceptor {
public:
    explicit TcpAcceptor(event::Loop *loop);
    virtual ~TcpAcceptor();

public:
    bool initialize(const SockAddr &bind_addr, int listen_backlog);

    using NewConnectionCallback = std::function<void(TcpConnection *)>;
    void set_new_connection_callback(NewConnectionCallback cb) {
        m_new_conn_cb = std::move(cb);
    }

    bool start();
    bool stop();

    void cleanup();

protected:
    virtual SocketFd create_socket(SockAddr::Type addr_type);
    virtual int bind_address(SocketFd sock_fd, const SockAddr &bind_addr);

    void on_socket_read(uint32_t events); //! 处理新的连接请求
    void on_client_connected();

private:
    event::Loop *m_loop = nullptr;
    SockAddr m_bind_addr;

    NewConnectionCallback m_new_conn_cb;

    SocketFd m_listen_fd;
    std::unique_ptr<event::EpollFdEvent> m_read_event{};
};
} // namespace ibox::network
